package com.sciencep.pro.core.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sciencep.pro.common.config.Constant;
import com.sciencep.pro.common.domain.OscaConstant;
import com.sciencep.pro.common.domain.QueryRequest;
import com.sciencep.pro.common.domain.ResponseResult;
import com.sciencep.pro.common.utils.SortUtil;
import com.sciencep.pro.core.dao.ProTypeMapper;
import com.sciencep.pro.core.domain.dto.project.ProTypeTO;
import com.sciencep.pro.core.domain.dto.protypenode.ProTypeNodeTO;
import com.sciencep.pro.core.domain.dto.user.UserDetail;
import com.sciencep.pro.core.domain.dto.workdailylog.WorkdailyLogTO;
import com.sciencep.pro.core.domain.entity.ProBaseInfo;
import com.sciencep.pro.core.domain.entity.ProNode;
import com.sciencep.pro.core.domain.entity.ProType;
import com.sciencep.pro.core.domain.vo.protypenode.ProTypeNodeVO;
import com.sciencep.pro.core.service.IProBaseInfoService;
import com.sciencep.pro.core.service.IProNodeService;
import com.sciencep.pro.core.service.IProTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Sciencep
 */
@Service
@Transactional
public class ProTypeServiceImpl extends ServiceImpl<ProTypeMapper, ProType> implements IProTypeService {

    @Autowired
    @Lazy
    private IProTypeService proTypeService;

    @Autowired
    private IProNodeService proNodeService;

    @Autowired
    @Lazy
    private IProBaseInfoService proBaseInfoService;

    @Override
    public List<ProTypeTO> getTypeList() {

        List<ProType> nodes = this.list(new LambdaQueryWrapper<ProType>().eq(ProType::getIsDel, Constant.IsDelete.NO));
        if (CollUtil.isEmpty(nodes)) {
            return new ArrayList<>(0);
        }
        List<ProTypeTO> result = new ArrayList<>();
        nodes.forEach(o ->
                result.add(new ProTypeTO(String.valueOf(o.getId()), o.getTypeCode(), o.getTypeName()))
        );

        return result;
    }

    @Override
    public Page<ProTypeNodeTO> getTypeNodeList(QueryRequest queryRequest) {
        Page<WorkdailyLogTO> page = new Page<>();
        SortUtil.handlePageSort(queryRequest, page, "id", OscaConstant.ORDER_DESC, false);
        return baseMapper.getProjectTypeList(page);
    }

    @Override
    public ResponseResult<ProTypeNodeTO> saveTypeNode(ProTypeNodeVO proTypeNodeVO, UserDetail userDetail) {
        if (proTypeService.getOne(new LambdaQueryWrapper<ProType>().eq(ProType::getTypeName, proTypeNodeVO.getTypeName()).eq(ProType::getIsDel, Constant.IsDelete.NO)) != null) {
            return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.TYPE_NAME_ERROR);
        }
        if (proTypeService.getOne(new LambdaQueryWrapper<ProType>().eq(ProType::getTypeCode, proTypeNodeVO.getTypeCode()).eq(ProType::getIsDel, Constant.IsDelete.NO)) != null) {
            return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.TYPE_TYPECODE_ERROR);
        }
        if (!CollUtil.isNotEmpty(proTypeNodeVO.getProNodeList())) {
            return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.PROCESS_ERROR);
        } else {
            for (int i = 0; i < proTypeNodeVO.getProNodeList().size(); i++) {
                for (int j = i + 1; j < proTypeNodeVO.getProNodeList().size(); j++) {
                    if (proTypeNodeVO.getProNodeList().get(i).equals(proTypeNodeVO.getProNodeList().get(j))) {
                        return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.PROCESS_REPEAT);
                    }
                }
            }
        }
        ProType proType = new ProType();
        proType.setTypeName(proTypeNodeVO.getTypeName());
        proType.setTypeCode(proTypeNodeVO.getTypeCode());
        proType.setCreateUserId(userDetail.getUserId());
        proType.setCreateUserName(userDetail.getUserName());
        proTypeService.save(proType);
        Long typeId = proType.getId();
        if (CollUtil.isNotEmpty(proTypeNodeVO.getProNodeList())) {
            List<ProNode> proNodeList = new ArrayList<>();
            proTypeNodeVO.getProNodeList().forEach(e -> {
                ProNode proNode = new ProNode();
                proNode.setTypeId(typeId.toString());
                proNode.setNodeName(e.getNodeName());
                proNode.setCreateUserId(userDetail.getUserId());
                proNode.setCreateUserName(userDetail.getUserName());
                proNodeList.add(proNode);
            });
            proNodeService.saveBatch(proNodeList);
        }
        return new ResponseResult<ProTypeNodeTO>().success();
    }

    @Override
    public ResponseResult<ProTypeNodeTO> deleteTypeNode(String typeId, UserDetail userDetail) {
        if (CollUtil.isNotEmpty(proBaseInfoService.list(new LambdaQueryWrapper<ProBaseInfo>().eq(ProBaseInfo::getProTypeId, typeId).eq(ProBaseInfo::getIsDel,Constant.IsDelete.NO)))) {
            return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.PROCESS_PROCEED);
        }
        boolean isType;
        boolean isNode;
        ProType proType = new ProType();
        proType.setId(Long.valueOf(typeId));
        proType.setIsDel(Constant.IsDelete.YES);
        proType.setModifyUserId(userDetail.getUserId());
        proType.setModifyUserName(userDetail.getUserName());
        isType = proTypeService.updateById(proType);

        ProNode proNode = new ProNode();
        proNode.setIsDel(Constant.IsDelete.YES);
        proNode.setModifyUserId(userDetail.getUserId());
        proNode.setModifyUserName(userDetail.getUserName());
        isNode = proNodeService.update(proNode, new LambdaQueryWrapper<ProNode>().eq(ProNode::getTypeId, typeId));

        if (isType && isNode) {
            return new ResponseResult<ProTypeNodeTO>().success();
        } else {
            return new ResponseResult<ProTypeNodeTO>().failure();
        }
    }

    @Override
    public ResponseResult<ProTypeNodeTO> updateTypeNode(ProTypeNodeVO proTypeNodeVO, UserDetail userDetail) {
        if (CollUtil.isNotEmpty(proBaseInfoService.list(new LambdaQueryWrapper<ProBaseInfo>().eq(ProBaseInfo::getProTypeId, proTypeNodeVO.getId()).eq(ProBaseInfo::getIsDel,Constant.IsDelete.NO)))) {
            return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.PROCESS_PROCEED_UPDATE);
        }
        if (proTypeService.getOne(new LambdaQueryWrapper<ProType>().
                ne(ProType::getId, proTypeNodeVO.getId()).
                eq(ProType::getTypeName, proTypeNodeVO.getTypeName()).
                eq(ProType::getIsDel, Constant.IsDelete.NO)) != null) {
            return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.TYPE_NAME_ERROR);
        }
        if (proTypeService.getOne(new LambdaQueryWrapper<ProType>().
                ne(ProType::getId, proTypeNodeVO.getId()).
                eq(ProType::getTypeCode, proTypeNodeVO.getTypeCode()).
                eq(ProType::getIsDel, Constant.IsDelete.NO)) != null) {
            return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.TYPE_TYPECODE_ERROR);
        }
        if (!CollUtil.isNotEmpty(proTypeNodeVO.getProNodeList())) {
            return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.PROCESS_ERROR);
        } else {
            for (int i = 0; i < proTypeNodeVO.getProNodeList().size(); i++) {
                for (int j = i + 1; j < proTypeNodeVO.getProNodeList().size(); j++) {
                    if (proTypeNodeVO.getProNodeList().get(i).getNodeName().equals(proTypeNodeVO.getProNodeList().get(j).getNodeName())) {
                        return new ResponseResult<ProTypeNodeTO>().failure(Constant.ErrorCode.SYSTEM_ERROR, Constant.ErrorMessage.PROCESS_REPEAT);
                    }
                }
            }
        }
        ProType proType = new ProType();
        proType.setId(Long.valueOf(proTypeNodeVO.getId()));
        proType.setTypeName(proTypeNodeVO.getTypeName());
        proType.setTypeCode(proTypeNodeVO.getTypeCode());
        proType.setModifyUserId(userDetail.getUserId());
        proType.setModifyUserName(userDetail.getUserName());
        proTypeService.updateById(proType);

        if (CollUtil.isNotEmpty(proTypeNodeVO.getProNodeList())) {
            //先全部删除
            ProNode proNodeDel = new ProNode();
            proNodeDel.setIsDel(Constant.IsDelete.YES);
            proNodeService.update(proNodeDel, new LambdaQueryWrapper<ProNode>().eq(ProNode::getTypeId, proTypeNodeVO.getId()));

            List<ProNode> insertProNodeList = new ArrayList<>();
            proTypeNodeVO.getProNodeList().forEach(e -> {

                ProNode proNode = new ProNode();
                proNode.setTypeId(proTypeNodeVO.getId());
                proNode.setNodeName(e.getNodeName());
                proNode.setCreateUserId(userDetail.getUserId());
                proNode.setCreateUserName(userDetail.getUserName());
                insertProNodeList.add(proNode);
            });
            proNodeService.saveBatch(insertProNodeList);
        }

        return new ResponseResult<ProTypeNodeTO>().success();
    }


}
